//
//  main.c
//  remote-execute
//
//  Created by  AbbyCin on 10/28/14.
//  Copyright (c) 2014  AbbyCin. All rights reserved.
//

#include "Header.h"
#include "sock_act.h"

void handler(int sig)
{
    while(waitpid(-1, NULL, WNOHANG) != -1)
        continue;
}

int do_cmd(int fd)
{
    int status;
    char *cmd = NULL;
	
	cmd = malloc(cmd_len);
    
	read(fd, cmd, cmd_len);
	status = system(cmd);
    write(fd,&status,sizeof(status));
	free(cmd);
	close(fd);
    
	return status;
}

int main(int argc, const char * argv[])
{
    int sfd = 0;
    int acfd = 0;
    char *name = NULL;
    struct sockaddr_in client;
	socklen_t client_len = sizeof(client);
    
    bzero(&client,client_len);
    name = malloc(512);

    setuid(getuid());       /* drop privilege */
    chroot("/");            /* jailed in / */
    
    sfd=Listen(argv[1],"30920", NULL, BACK_LOG);    /* bind and listen; addr argv[1], port 30920*/
    if(sfd == -1)
        syslog(LOG_ERR, "Listen errno: %s",strerror(errno));
    
    if((sfd = dup2(sfd, 1)) == -1)
        syslog(LOG_ERR, "dup 1 failed: %s",strerror(errno));
    if((sfd = dup2(sfd, 2)) == -1)
        syslog(LOG_ERR, "dup 2 failed: %s",strerror(errno));
    
    signal(SIGCHLD,handler);  		/* replace sigaciton to signal */
    
    for(;;)
    {
        if((acfd = accept(sfd, (SA *)&client, &client_len)) == -1)
            if(errno != EINTR)
                syslog(LOG_ERR,"accept error: %s",strerror(errno));

        inet_ntop(AF_INET, &client.sin_addr, name, client_len);
        syslog(LOG_INFO, "client from: %s : %d",name,ntohs(client.sin_port));
        memset(name,0,512);
        
        switch (fork())
		{
            case -1:
                syslog(LOG_ERR,"fork error: %s",strerror(errno));
                exit(1);
            case 0:
                if(do_cmd(acfd) == -1)
                    syslog(LOG_ERR,"do_cmd error: %s",strerror(errno));
                _exit(0);
            default:
                break;
        }
        close(acfd);
    }
}
